//
//  IMVibrateService.m
//  DualMediationSDK
//
//  Created by YeJary on 2025/1/27.
//

#import "IMVibrateService.h"
#import "../../Utils/Logger/IMLogUtils.h"
#import <AudioToolbox/AudioToolbox.h>
#import <Foundation/Foundation.h>

#if TARGET_OS_IOS
#import <UIKit/UIKit.h>
#endif

// iOS 10+ 触觉反馈
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000
#import <UIKit/UIFeedbackGenerator.h>
#endif

@interface IMVibrateService ()

@property (nonatomic, strong) NSMutableDictionary<NSString *, NSTimer *> *activeVibrations;
@property (nonatomic, strong) NSMutableDictionary<NSString *, IMVibrateConfig *> *vibrateConfigs;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *vibrateCounts;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *vibrateStates; // 0:运行 1:暂停 2:取消
@property (nonatomic, strong) dispatch_queue_t vibrateQueue;

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000
@property (nonatomic, strong) UIImpactFeedbackGenerator *lightImpactGenerator;
@property (nonatomic, strong) UIImpactFeedbackGenerator *mediumImpactGenerator;
@property (nonatomic, strong) UIImpactFeedbackGenerator *heavyImpactGenerator;
@property (nonatomic, strong) UISelectionFeedbackGenerator *selectionGenerator;
@property (nonatomic, strong) UINotificationFeedbackGenerator *notificationGenerator;
#endif

@end

@implementation IMVibrateService

static IMVibrateService *_sharedService = nil;
static dispatch_once_t _onceToken;

+ (instancetype)sharedService {
    dispatch_once(&_onceToken, ^{
        _sharedService = [[IMVibrateService alloc] init];
    });
    return _sharedService;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        _activeVibrations = [NSMutableDictionary dictionary];
        _vibrateConfigs = [NSMutableDictionary dictionary];
        _vibrateCounts = [NSMutableDictionary dictionary];
        _vibrateStates = [NSMutableDictionary dictionary];
        _vibrateQueue = dispatch_queue_create("com.dualmediationsdk.vibrate", DISPATCH_QUEUE_SERIAL);
        
        [self setupHapticGenerators];
        [IMLogUtils info:IMLogTagAd format:@"IMVibrateService initialized"];
    }
    return self;
}

- (void)setupHapticGenerators {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000
    if (@available(iOS 10.0, *)) {
        self.lightImpactGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
        self.mediumImpactGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium];
        self.heavyImpactGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy];
        self.selectionGenerator = [[UISelectionFeedbackGenerator alloc] init];
        self.notificationGenerator = [[UINotificationFeedbackGenerator alloc] init];
        
        [self.lightImpactGenerator prepare];
        [self.mediumImpactGenerator prepare];
        [self.heavyImpactGenerator prepare];
        [self.selectionGenerator prepare];
        [self.notificationGenerator prepare];
    }
#endif
}

#pragma mark - 基础震动接口

- (IMVibrateResult *)vibrateWithDuration:(NSTimeInterval)duration
                              completion:(IMVibrateCompletionBlock)completion {
    IMVibrateConfig *config = [IMVibrateConfig configWithDuration:duration];
    return [self vibrateWithConfig:config completion:completion];
}

- (IMVibrateResult *)vibrateWithPattern:(NSArray<NSNumber *> *)pattern
                            repeatCount:(NSInteger)repeatCount
                             completion:(IMVibrateCompletionBlock)completion {
    IMVibrateConfig *config = [IMVibrateConfig configWithPattern:pattern repeatCount:repeatCount];
    return [self vibrateWithConfig:config completion:completion];
}

- (IMVibrateResult *)vibrateWithType:(IMVibrateType)type
                           intensity:(IMVibrateIntensity)intensity
                          completion:(IMVibrateCompletionBlock)completion {
    IMVibrateConfig *config = [IMVibrateConfig configWithType:type intensity:intensity];
    return [self vibrateWithConfig:config completion:completion];
}

#pragma mark - 高级震动接口

- (IMVibrateResult *)vibrateWithConfig:(IMVibrateConfig *)config
                            completion:(IMVibrateCompletionBlock)completion {
    return [self vibrateWithConfig:config progress:nil completion:completion];
}

- (IMVibrateResult *)vibrateWithConfig:(IMVibrateConfig *)config
                              progress:(IMVibrateProgressBlock)progress
                            completion:(IMVibrateCompletionBlock)completion {
    
    // 参数验证
    if (!config) {
        IMVibrateResult *result = [IMVibrateResult failureWithCode:-1000 message:@"震动配置不能为空"];
        [IMLogUtils error:IMLogTagAd format:@"Vibrate failed: config is nil"];
        if (completion) {
            completion(result);
        }
        return result;
    }
    
    if (![config isValid]) {
        IMVibrateResult *result = [IMVibrateResult failureWithCode:-1001 message:@"震动配置无效"];
        [IMLogUtils error:IMLogTagAd format:@"Vibrate failed: invalid config %@", config];
        if (completion) {
            completion(result);
        }
        return result;
    }
    
    if (![self isVibrateSupported]) {
        IMVibrateResult *result = [IMVibrateResult failureWithCode:-1002 message:@"设备不支持震动"];
        [IMLogUtils warning:IMLogTagAd format:@"Vibrate failed: device not supported"];
        if (completion) {
            completion(result);
        }
        return result;
    }
    
    // 生成震动ID
    NSString *vibrateId = [NSString stringWithFormat:@"vibrate_%@_%ld", 
                          [[NSUUID UUID] UUIDString], (long)[[NSDate date] timeIntervalSince1970]];
    
    [IMLogUtils info:IMLogTagAd format:@"Starting vibration with ID: %@, config: %@", vibrateId, [config configDescription]];
    
    // 保存配置和状态
    self.vibrateConfigs[vibrateId] = config;
    self.vibrateCounts[vibrateId] = @0;
    self.vibrateStates[vibrateId] = @0; // 运行状态
    
    // 异步执行震动
    dispatch_async(self.vibrateQueue, ^{
        [self executeVibrateWithId:vibrateId config:config progress:progress completion:completion];
    });
    
    return [IMVibrateResult successWithVibrateId:vibrateId];
}

#pragma mark - 震动执行

- (void)executeVibrateWithId:(NSString *)vibrateId
                      config:(IMVibrateConfig *)config
                    progress:(IMVibrateProgressBlock)progress
                  completion:(IMVibrateCompletionBlock)completion {
    
    if (config.mode == IMVibrateModeOnce) {
        [self executeSingleVibrateWithId:vibrateId config:config completion:completion];
    } else if (config.mode == IMVibrateModePattern) {
        [self executePatternVibrateWithId:vibrateId config:config progress:progress completion:completion];
    } else if (config.mode == IMVibrateModeRepeat) {
        [self executeRepeatVibrateWithId:vibrateId config:config progress:progress completion:completion];
    }
}

- (void)executeSingleVibrateWithId:(NSString *)vibrateId
                            config:(IMVibrateConfig *)config
                        completion:(IMVibrateCompletionBlock)completion {
    
    dispatch_async(dispatch_get_main_queue(), ^{
        if ([self.vibrateStates[vibrateId] integerValue] != 0) {
            return; // 已取消或暂停
        }
        
        [self performVibrateWithType:config.type intensity:config.intensity];
        
        if (config.duration > 0) {
            // 使用定时器控制震动时长
            NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:config.duration / 1000.0
                                                              target:self
                                                            selector:@selector(vibrateTimerFired:)
                                                            userInfo:@{@"vibrateId": vibrateId, @"completion": completion ? [NSValue valueWithPointer:(__bridge const void *)(completion)] : [NSNull null]}
                                                             repeats:NO];
            self.activeVibrations[vibrateId] = timer;
        } else {
            // 立即完成
            [self completeVibrateWithId:vibrateId completion:completion];
        }
    });
}

- (void)executePatternVibrateWithId:(NSString *)vibrateId
                             config:(IMVibrateConfig *)config
                           progress:(IMVibrateProgressBlock)progress
                         completion:(IMVibrateCompletionBlock)completion {
    
    [self executePatternVibrateStep:0 withId:vibrateId config:config progress:progress completion:completion];
}

- (void)executePatternVibrateStep:(NSInteger)step
                           withId:(NSString *)vibrateId
                           config:(IMVibrateConfig *)config
                         progress:(IMVibrateProgressBlock)progress
                       completion:(IMVibrateCompletionBlock)completion {
    
    if ([self.vibrateStates[vibrateId] integerValue] != 0) {
        return; // 已取消或暂停
    }
    
    if (step >= config.pattern.count) {
        // 一轮完成，检查是否需要重复
        NSInteger currentCount = [self.vibrateCounts[vibrateId] integerValue] + 1;
        self.vibrateCounts[vibrateId] = @(currentCount);
        
        if (progress) {
            dispatch_async(dispatch_get_main_queue(), ^{
                progress(vibrateId, currentCount);
            });
        }
        
        if (config.repeatCount == 0 || currentCount < config.repeatCount) {
            // 继续重复
            [self executePatternVibrateStep:0 withId:vibrateId config:config progress:progress completion:completion];
        } else {
            // 完成
            [self completeVibrateWithId:vibrateId completion:completion];
        }
        return;
    }
    
    NSTimeInterval interval = [config.pattern[step] doubleValue] / 1000.0;
    
    if (step % 2 == 0) {
        // 震动
        dispatch_async(dispatch_get_main_queue(), ^{
            [self performVibrateWithType:config.type intensity:config.intensity];
        });
    }
    
    // 设置下一步定时器
    dispatch_async(dispatch_get_main_queue(), ^{
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:interval
                                                          target:self
                                                        selector:@selector(patternTimerFired:)
                                                        userInfo:@{
                                                            @"vibrateId": vibrateId,
                                                            @"step": @(step + 1),
                                                            @"config": config,
                                                            @"progress": progress ? [NSValue valueWithPointer:(__bridge const void *)(progress)] : [NSNull null],
                                                            @"completion": completion ? [NSValue valueWithPointer:(__bridge const void *)(completion)] : [NSNull null]
                                                        }
                                                         repeats:NO];
        self.activeVibrations[vibrateId] = timer;
    });
}

- (void)executeRepeatVibrateWithId:(NSString *)vibrateId
                            config:(IMVibrateConfig *)config
                          progress:(IMVibrateProgressBlock)progress
                        completion:(IMVibrateCompletionBlock)completion {
    
    [self executeRepeatVibrateStepWithId:vibrateId config:config progress:progress completion:completion];
}

- (void)executeRepeatVibrateStepWithId:(NSString *)vibrateId
                                config:(IMVibrateConfig *)config
                              progress:(IMVibrateProgressBlock)progress
                            completion:(IMVibrateCompletionBlock)completion {
    
    if ([self.vibrateStates[vibrateId] integerValue] != 0) {
        return; // 已取消或暂停
    }
    
    NSInteger currentCount = [self.vibrateCounts[vibrateId] integerValue] + 1;
    self.vibrateCounts[vibrateId] = @(currentCount);
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [self performVibrateWithType:config.type intensity:config.intensity];
        
        if (progress) {
            progress(vibrateId, currentCount);
        }
    });
    
    // 检查是否需要继续重复
    if (config.repeatCount == 0 || currentCount < config.repeatCount) {
        NSTimeInterval interval = config.duration > 0 ? config.duration / 1000.0 : 1.0;
        
        dispatch_async(dispatch_get_main_queue(), ^{
            NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:interval
                                                              target:self
                                                            selector:@selector(repeatTimerFired:)
                                                            userInfo:@{
                                                                @"vibrateId": vibrateId,
                                                                @"config": config,
                                                                @"progress": progress ? [NSValue valueWithPointer:(__bridge const void *)(progress)] : [NSNull null],
                                                                @"completion": completion ? [NSValue valueWithPointer:(__bridge const void *)(completion)] : [NSNull null]
                                                            }
                                                             repeats:NO];
            self.activeVibrations[vibrateId] = timer;
        });
    } else {
        // 完成
        [self completeVibrateWithId:vibrateId completion:completion];
    }
}

#pragma mark - 定时器回调

- (void)vibrateTimerFired:(NSTimer *)timer {
    NSDictionary *userInfo = timer.userInfo;
    NSString *vibrateId = userInfo[@"vibrateId"];
    IMVibrateCompletionBlock completion = nil;
    if (![userInfo[@"completion"] isEqual:[NSNull null]]) {
        completion = (__bridge IMVibrateCompletionBlock)([userInfo[@"completion"] pointerValue]);
    }
    
    [self completeVibrateWithId:vibrateId completion:completion];
}

- (void)patternTimerFired:(NSTimer *)timer {
    NSDictionary *userInfo = timer.userInfo;
    NSString *vibrateId = userInfo[@"vibrateId"];
    NSInteger step = [userInfo[@"step"] integerValue];
    IMVibrateConfig *config = userInfo[@"config"];
    IMVibrateProgressBlock progress = nil;
    if (![userInfo[@"progress"] isEqual:[NSNull null]]) {
        progress = (__bridge IMVibrateProgressBlock)([userInfo[@"progress"] pointerValue]);
    }
    IMVibrateCompletionBlock completion = nil;
    if (![userInfo[@"completion"] isEqual:[NSNull null]]) {
        completion = (__bridge IMVibrateCompletionBlock)([userInfo[@"completion"] pointerValue]);
    }
    
    [self executePatternVibrateStep:step withId:vibrateId config:config progress:progress completion:completion];
}

- (void)repeatTimerFired:(NSTimer *)timer {
    NSDictionary *userInfo = timer.userInfo;
    NSString *vibrateId = userInfo[@"vibrateId"];
    IMVibrateConfig *config = userInfo[@"config"];
    IMVibrateProgressBlock progress = nil;
    if (![userInfo[@"progress"] isEqual:[NSNull null]]) {
        progress = (__bridge IMVibrateProgressBlock)([userInfo[@"progress"] pointerValue]);
    }
    IMVibrateCompletionBlock completion = nil;
    if (![userInfo[@"completion"] isEqual:[NSNull null]]) {
        completion = (__bridge IMVibrateCompletionBlock)([userInfo[@"completion"] pointerValue]);
    }
    
    [self executeRepeatVibrateStepWithId:vibrateId config:config progress:progress completion:completion];
}

#pragma mark - 震动执行

- (void)performVibrateWithType:(IMVibrateType)type intensity:(IMVibrateIntensity)intensity {
    
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000
    if (@available(iOS 10.0, *)) {
        switch (type) {
            case IMVibrateTypeLight:
                [self.lightImpactGenerator impactOccurred];
                break;
            case IMVibrateTypeMedium:
                [self.mediumImpactGenerator impactOccurred];
                break;
            case IMVibrateTypeHeavy:
                [self.heavyImpactGenerator impactOccurred];
                break;
            case IMVibrateTypeSelection:
                [self.selectionGenerator selectionChanged];
                break;
            case IMVibrateTypeImpact:
                switch (intensity) {
                    case IMVibrateIntensityLight:
                        [self.lightImpactGenerator impactOccurred];
                        break;
                    case IMVibrateIntensityMedium:
                        [self.mediumImpactGenerator impactOccurred];
                        break;
                    case IMVibrateIntensityHeavy:
                        [self.heavyImpactGenerator impactOccurred];
                        break;
                }
                break;
            case IMVibrateTypeNotification:
                [self.notificationGenerator notificationOccurred:UINotificationFeedbackTypeSuccess];
                break;
            case IMVibrateTypeSuccess:
                [self.notificationGenerator notificationOccurred:UINotificationFeedbackTypeSuccess];
                break;
            case IMVibrateTypeWarning:
                [self.notificationGenerator notificationOccurred:UINotificationFeedbackTypeWarning];
                break;
            case IMVibrateTypeError:
                [self.notificationGenerator notificationOccurred:UINotificationFeedbackTypeError];
                break;
        }
        return;
    }
#endif
    
    // iOS 9及以下版本使用AudioToolbox
    AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}

- (void)completeVibrateWithId:(NSString *)vibrateId completion:(IMVibrateCompletionBlock)completion {
    
    // 清理资源
    [self.activeVibrations[vibrateId] invalidate];
    [self.activeVibrations removeObjectForKey:vibrateId];
    [self.vibrateConfigs removeObjectForKey:vibrateId];
    [self.vibrateCounts removeObjectForKey:vibrateId];
    [self.vibrateStates removeObjectForKey:vibrateId];
    
    [IMLogUtils info:IMLogTagAd format:@"Vibration completed with ID: %@", vibrateId];
    
    if (completion) {
        dispatch_async(dispatch_get_main_queue(), ^{
            completion([IMVibrateResult successWithVibrateId:vibrateId]);
        });
    }
}

#pragma mark - 震动控制

- (BOOL)cancelVibrateWithId:(NSString *)vibrateId {
    if (!vibrateId || !self.activeVibrations[vibrateId]) {
        return NO;
    }
    
    [IMLogUtils info:IMLogTagAd format:@"Cancelling vibration with ID: %@", vibrateId];
    
    self.vibrateStates[vibrateId] = @2; // 取消状态
    [self.activeVibrations[vibrateId] invalidate];
    [self.activeVibrations removeObjectForKey:vibrateId];
    [self.vibrateConfigs removeObjectForKey:vibrateId];
    [self.vibrateCounts removeObjectForKey:vibrateId];
    [self.vibrateStates removeObjectForKey:vibrateId];
    
    return YES;
}

- (NSInteger)cancelAllVibrations {
    NSInteger count = self.activeVibrations.count;
    
    [IMLogUtils info:IMLogTagAd format:@"Cancelling all vibrations, count: %ld", (long)count];
    
    for (NSTimer *timer in self.activeVibrations.allValues) {
        [timer invalidate];
    }
    
    [self.activeVibrations removeAllObjects];
    [self.vibrateConfigs removeAllObjects];
    [self.vibrateCounts removeAllObjects];
    [self.vibrateStates removeAllObjects];
    
    return count;
}

- (BOOL)pauseVibrateWithId:(NSString *)vibrateId {
    if (!vibrateId || !self.activeVibrations[vibrateId]) {
        return NO;
    }
    
    [IMLogUtils info:IMLogTagAd format:@"Pausing vibration with ID: %@", vibrateId];
    
    self.vibrateStates[vibrateId] = @1; // 暂停状态
    return YES;
}

- (BOOL)resumeVibrateWithId:(NSString *)vibrateId {
    if (!vibrateId || !self.vibrateConfigs[vibrateId]) {
        return NO;
    }
    
    if ([self.vibrateStates[vibrateId] integerValue] != 1) {
        return NO; // 不是暂停状态
    }
    
    [IMLogUtils info:IMLogTagAd format:@"Resuming vibration with ID: %@", vibrateId];
    
    self.vibrateStates[vibrateId] = @0; // 运行状态
    
    // 重新启动震动
    IMVibrateConfig *config = self.vibrateConfigs[vibrateId];
    dispatch_async(self.vibrateQueue, ^{
        [self executeVibrateWithId:vibrateId config:config progress:nil completion:nil];
    });
    
    return YES;
}

#pragma mark - 震动状态查询

- (BOOL)isVibrateSupported {
    // 检查设备是否支持震动
#if TARGET_OS_IOS
    return [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone;
#else
    return NO;
#endif
}

- (BOOL)isHapticFeedbackSupported {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000
    if (@available(iOS 10.0, *)) {
        return [self isVibrateSupported];
    }
#endif
    return NO;
}

- (NSInteger)activeVibrationsCount {
    return self.activeVibrations.count;
}

- (NSString *)getVibrateStatus:(NSString *)vibrateId {
    if (!vibrateId) {
        return nil;
    }
    
    NSNumber *state = self.vibrateStates[vibrateId];
    if (!state) {
        return @"不存在";
    }
    
    switch ([state integerValue]) {
        case 0:
            return @"运行中";
        case 1:
            return @"已暂停";
        case 2:
            return @"已取消";
        default:
            return @"未知状态";
    }
}

#pragma mark - 预设震动模式

- (IMVibrateResult *)vibrateSuccess:(IMVibrateCompletionBlock)completion {
    return [self vibrateWithType:IMVibrateTypeSuccess intensity:IMVibrateIntensityMedium completion:completion];
}

- (IMVibrateResult *)vibrateWarning:(IMVibrateCompletionBlock)completion {
    return [self vibrateWithType:IMVibrateTypeWarning intensity:IMVibrateIntensityMedium completion:completion];
}

- (IMVibrateResult *)vibrateError:(IMVibrateCompletionBlock)completion {
    return [self vibrateWithType:IMVibrateTypeError intensity:IMVibrateIntensityHeavy completion:completion];
}

- (IMVibrateResult *)vibrateSelection:(IMVibrateCompletionBlock)completion {
    return [self vibrateWithType:IMVibrateTypeSelection intensity:IMVibrateIntensityLight completion:completion];
}

- (IMVibrateResult *)vibrateImpact:(IMVibrateCompletionBlock)completion {
    return [self vibrateWithType:IMVibrateTypeImpact intensity:IMVibrateIntensityMedium completion:completion];
}

#pragma mark - Description

- (NSString *)description {
    return [NSString stringWithFormat:@"<%@: %p> activeVibrations:%ld",
            NSStringFromClass([self class]), self, (long)self.activeVibrations.count];
}

@end